<?php
namespace App\Api\Services;

use App\Api\Models\AdminModel;
use App\Helper\DBRSAUtil;
use App\Api\Models\ModuleModel;
use App\Api\Models\RoleSettingModel;
use App\Api\Models\SystemConfigModel;
use App\Http\Controllers\Api\SyncDataController;
use App\V3\Api\Models\AdminAddendumModel;
use App\V3\Api\Models\VipSettingModel;
use Illuminate\Support\Facades\Redis;

class LoginService
{
    const SALT = 'storage';

    static public function defaultCodeLog($data, $deviceId, $minicode)
    {
        $userInfo = AdminModel::where([
            'username' => $data['mobile'],
            'parent_id' => 0,
            'delete_flag' => 0
        ])->first();

        if(!empty($userInfo)) {
            $userId = empty($userInfo)?$result['data']['user_id']:$userInfo['id'];//子账号(账号类型为主账号时子账号同主账号)
            $mainUserId = $userId;//主账号id

            $result = SELF::common(
                $userId,
                $mainUserId,
                0,
                $data['device'],
                $userInfo['company_name'],
                1,
                $userInfo['out_storage_way']
            );

            $roleInfo = RoleSettingModel::where('role_id', $userInfo['admin_role'])->first();

            $userFirstModuleArr = array_filter(explode(',', $roleInfo['first_module']), function($v) { return $v !== ''; });
            $userSecondModuleArr = array_filter(explode(',', $roleInfo['second_module']), function($v) { return $v !== ''; });

            $result['data']['nickname'] = $userInfo['nickname'];
            $result['data']['parent_id'] = $userInfo['id'];
            $result['data']['out_storage_way'] = $userInfo['out_storage_way'];
            $result['data']['is_sync'] = $userInfo['is_sync'];
            $moduleInfo = SELF::moduleCommon($userFirstModuleArr, $userSecondModuleArr);
            $result['data']['bind_id'] = $userInfo['bind_id'];
            $result['data']['invite_num'] = $userInfo['invite_num'];
            $result['data']['invite_info'] = AdminService::inviteInfo($userInfo['id']);
            $result['data']['is_bind_openid'] = empty($userInfo['openid'])?0:1;

            if(!empty($deviceId) && $deviceId != 'null' && $deviceId != null) {
                AdminModel::where('id', $userId)->update([
                    'device_id' => $deviceId
                ]);
            }

            if($userInfo['is_sync'] == 0) {
                SyncDataController::syncMaterielCost($mainUserId, $userInfo['batch_title']);

                AdminModel::where('id', $mainUserId)->update(['is_sync' => 1]);
            }

            $adminArray = json_decode(Redis::get('admin_array'), true);

            $key = array_search($userId, empty($adminArray)?[]:$adminArray);

            //主账号权限发生变动后重新登录取消权限不足的提示
            if($key !== false) {
                unset($adminArray[$key]);
                Redis::SETEX('admin_array', 86400*15, json_encode($adminArray));
            }

            $result['data']['is_main'] = 1;//账号类型;0:子;1:主;
            $result['data']['module_info'] = $moduleInfo;
        }
        else {
            return ['code' => 1, 'msg' => '不存在的用户', 'data' => ''];
        }

        return $result;
    }

    //主账号登录
    static public function mainLogin($mobile, $code, $device, $miniCode, $bindId, $deviceId)
    {
        //比对用户输入的code和短信发送的code是否一致
        if(!Redis::exists($mobile.'_mobile_login')) {
            return ['code' => 1, 'msg' => '您输入的验证码无效，请重试', 'data' => ''];
        }
        else {
            if($code == Redis::get($mobile.'_mobile_login')) {//验证码一致
                $userInfo = AdminModel::where([
                    'username' => $mobile,
                    'parent_id' => 0,
                    'delete_flag' => 0
                ])->first();

                //用户不存在
                if(empty($userInfo)) {
                    $userId = SELF::register($mobile, $device, $miniCode, $bindId, $deviceId);
                    $userInfo = AdminModel::where('id', $userId)->first();
                }
                else if(!empty($userInfo)) {
                    $userId = empty($userInfo)?$result['data']['user_id']:$userInfo['id'];//子账号(账号类型为主账号时子账号同主账号)
                }

                $mainUserId = $userId;//主账号id

                if(Redis::exists('user_id_'.$userId.'_reset') && Redis::get('user_id_'.$userId.'_reset') == 1) {
                    Redis::del('user_id_'.$userId.'_reset');
                }

                if(Redis::GET('user_id_'.$userId.'_disabled') && Redis::GET('user_id_'.$userId.'_disabled') == 1) {
                    Redis::del('user_id_'.$userId.'_disabled');
                }

                $result = SELF::common(
                    $userId,
                    $mainUserId,
                    0,
                    $device,
                    $userInfo['company_name'],
                    0,
                    $userInfo['out_storage_way']
                );

                $roleInfo = RoleSettingModel::where('role_id', $userInfo['admin_role'])->first();

                $userFirstModuleArr = array_filter(explode(',', $roleInfo['first_module']), function($v) { return $v !== ''; });
                $userSecondModuleArr = array_filter(explode(',', $roleInfo['second_module']), function($v) { return $v !== ''; });

                $result['data']['nickname'] = $userInfo['nickname'];
                $moduleInfo = SELF::moduleCommon($userFirstModuleArr, $userSecondModuleArr);

                $result['data']['parent_id'] = $userInfo['id'];
                $result['data']['out_storage_way'] = $userInfo['out_storage_way'];
                $result['data']['bind_id'] = $userInfo['bind_id'];
                $result['data']['is_sync'] = $userInfo['is_sync'];
                $result['data']['invite_num'] = $userInfo['invite_num'];
                $result['data']['invite_info'] = AdminService::inviteInfo($userInfo['bind_id']);
                $result['data']['is_main'] = 1;//账号类型;0:子;1:主;
                $result['data']['module_info'] = $moduleInfo;
                $result['data']['is_bind_openid'] = empty($userInfo['openid'])?0:1;

                if(!empty($deviceId) && $deviceId != 'null' && $deviceId != null) {
                    AdminModel::where('id', $userId)->update([
                        'device_id' => $deviceId
                    ]);
                }

                if($userInfo['is_sync'] == 0) {
                    SyncDataController::syncMaterielCost($mainUserId, $userInfo['batch_title']);

                    AdminModel::where('id', $mainUserId)->update(['is_sync' => 1]);
                }

                $adminArray = json_decode(Redis::get('admin_array'), true);

                $key = array_search($userId, empty($adminArray)?[]:$adminArray);

                //主账号权限发生变动后重新登录取消权限不足的提示
                if($key !== false) {
                    unset($adminArray[$key]);
                    Redis::SETEX('admin_array', 86400*15, json_encode($adminArray));
                }

                Redis::del($mobile.'_mobile_login');//登录成功后销毁验证码

                SELF::loginLimit($userId, $result['data']['token'], $device);

                return $result;
            }
            else {
                return ['code' => 1, 'msg' => '您输入的验证码有误，请重新输入', 'data' => ''];
            }
        }
    }

    static public function pwdLogin($mobile,$pwd,$device,$minicode,$bindId,$deviceId)
    {
        $userInfo = AdminModel::where([
            'username' => $mobile,
            'parent_id' => 0,
            'delete_flag' => 0
        ])->first();

        //用户不存在
        if($userInfo['password'] != md5(md5($pwd.SELF::SALT))) {//验证用户密码
            return ['code' => 1, 'msg' => '您输入的密码有误，请重新输入', 'data' => ''];
        }
//        if(empty($userInfo)) {
//            $userId = SELF::register($mobile, $device, $minicode, $bindId, $deviceId);
//            $userInfo = AdminModel::where('id', $userId)->first();
//        }
//        else {
//            if($userInfo['password'] != md5(md5($pwd.SELF::SALT))) {//验证用户密码
//                return ['code' => 1, 'msg' => '您输入的密码有误，请重新输入', 'data' => ''];
//            }
//        }

        $userId = $userInfo['id'];
        $mainUserId = $userId;//主账号id

        if(Redis::exists('user_id_'.$userId.'_reset') && Redis::get('user_id_'.$userId.'_reset') == 1) {
            Redis::del('user_id_'.$userId.'_reset');
        }

        if(Redis::GET('user_id_'.$userId.'_disabled') && Redis::GET('user_id_'.$userId.'_disabled') == 1) {
            Redis::del('user_id_'.$userId.'_disabled');
        }

        $result = SELF::common(
            $userId,
            $mainUserId,
            0,
            $device,
            $userInfo['company_name'],
            0,
            $userInfo['out_storage_way']
        );

        $roleInfo = RoleSettingModel::where('role_id', $userInfo['admin_role'])->first();

        $userFirstModuleArr = array_filter(explode(',', $roleInfo['first_module']), function($v) { return $v !== ''; });
        $userSecondModuleArr = array_filter(explode(',', $roleInfo['second_module']), function($v) { return $v !== ''; });

        $result['data']['nickname'] = $userInfo['nickname'];
        $moduleInfo = SELF::moduleCommon($userFirstModuleArr, $userSecondModuleArr);

        $result['data']['parent_id'] = $userInfo['id'];
        $result['data']['bind_id'] = $userInfo['bind_id'];
        $result['data']['invite_num'] = $userInfo['invite_num'];
        $result['data']['out_storage_way'] = $userInfo['out_storage_way'];
        $result['data']['is_sync'] = $userInfo['is_sync'];
        $result['data']['invite_info'] = AdminService::inviteInfo($userInfo['bind_id']);
        $result['data']['is_main'] = 1;//账号类型;0:子;1:主;
        $result['data']['module_info'] = $moduleInfo;
        $result['data']['is_bind_openid'] = empty($userInfo['openid'])?0:1;

        if($userInfo['is_sync'] == 0) {
            SyncDataController::syncMaterielCost($mainUserId, $userInfo['batch_title']);

            AdminModel::where('id', $mainUserId)->update(['is_sync' => 1]);
        }

        if(!empty($deviceId) && $deviceId != 'null' && $deviceId != null) {
            AdminModel::where('id', $userId)->update([
                'device_id' => $deviceId
            ]);
        }

        $adminArray = json_decode(Redis::get('admin_array'), true);

        $key = array_search($userId, empty($adminArray)?[]:$adminArray);

        //主账号权限发生变动后重新登录取消权限不足的提示
        if($key !== false) {
            unset($adminArray[$key]);
            Redis::SETEX('admin_array', 86400*15, json_encode($adminArray));
        }

        Redis::del($mobile.'_mobile_login');//登录成功后销毁验证码

        SELF::loginLimit($userId, $result['data']['token'], $device);

        return $result;
    }

    //子账号登录
    static public function userLogin($username, $password, $device, $deviceId, $minicode)
    {
        $userInfo  = AdminModel::where([
            'username' => $username,
            'delete_flag' => 0
        ])
            ->where('parent_id', '!=', 0)->first();

        if(empty($userInfo)) {
            return ['code' => 1, 'msg' => '用户不存在', 'data' => ''];
        }

        if(!$userInfo['is_active']) {
            return ['code' => 1, 'msg' => '当前账号已被禁用，请联系主账号管理员', 'data' => ''];
        }

        if($userInfo['password'] == md5(md5($password.SELF::SALT))) {//验证用户密码

            $result = SELF::common(
                $userInfo['id'],
                $userInfo['parent_id'],
                1,
                $device,
                $userInfo['company_name'],
                0,
                $userInfo['out_storage_way']
            );

            $userFirstModuleArr = array_filter(explode(',', $userInfo['first_module']), function($v) { return $v !== ''; });
            $userSecondModuleArr = array_filter(explode(',', $userInfo['second_module']), function($v) { return $v !== ''; });

            $moduleInfo = SELF::moduleCommon($userFirstModuleArr, $userSecondModuleArr);

            if(!empty($deviceId) && $deviceId != 'null' && $deviceId != null) {
                AdminModel::where('id', $userInfo['id'])->update([
                    'device_id' => $deviceId
                ]);
            }

            $mainInfo = AdminModel::where('id', $userInfo['parent_id'])->first();
            $result['data']['invite_num'] = $mainInfo['invite_num'];
            $result['data']['company_name'] = $mainInfo['company_name'];
            $result['data']['parent_id'] = $userInfo['parent_id'];
            $result['data']['is_sync'] = $mainInfo['is_sync'];
            $result['data']['bind_id'] = $mainInfo['bind_id'];
            $result['data']['invite_info'] = AdminService::inviteInfo($mainInfo['id']);
            $result['data']['is_default_pwd'] = $userInfo['is_default_pwd'];
            $result['data']['out_storage_way'] = $userInfo['out_storage_way'];
            $result['data']['is_main'] = 0;//账号类型;0:子;1:主;
            $result['data']['nickname'] = $userInfo['nickname'];
            $result['data']['module_info'] = $moduleInfo;
            $result['data']['is_bind_openid'] = empty($userInfo['openid'])?0:1;

            if(Redis::exists('user_id_'.$userInfo['id'].'_disabled') && Redis::get('user_id_'.$userInfo['id'].'_disabled') == 1) {
                Redis::del('user_id_'.$userInfo['id'].'_disabled');
            }

            if($mainInfo['is_sync'] == 0) {
                SyncDataController::syncMaterielCost($userInfo['parent_id'], $userInfo['batch_title']);

                AdminModel::where('id', $userInfo['parent_id'])
                    ->update(['is_sync' => 1]);
            }

            SELF::loginLimit($userInfo['id'], $result['data']['token'], $device);

            if(Redis::exists('user_id_'.$userInfo['id'].'_reset') && Redis::get('user_id_'.$userInfo['id'].'_reset') == 1) {
                Redis::del('user_id_'.$userInfo['id'].'_reset');
            }

            return $result;
        }
        else {
            return ['code' => 1, 'msg' => '密码错误', 'data' => ''];
        }
    }

    /**
     *
     * @param $userId 用户id
     * @param $mainUserId 主账号id
     * @param $userType 账号类型： 0-主 1-子
     * @param $device 设备类型
     * @param $companyName 公司名称
     * @param $isDefaultCode 是否默认验证码登陆
     * AUTHOR  : Sun Wu
     * DateTime: 2022/2/24 13:51
     * @return array
     */
    static private function common($userId, $mainUserId, $userType, $device, $companyName, $isDefaultCode, $outStorageWay)
    {
        $arr = [
            'userId'=>$userId,
            'mainUserId'=>$mainUserId,
            'userType'=>$userType,//账号类型： 0-主 1-子
            'type'=>$device,
            'is_default_code' => $isDefaultCode,
            'out_storage_way' => $outStorageWay
        ];

        $arr = json_encode($arr);
        $publicKey = SystemConfigModel::getConfigValue('public');
        $token = DBRSAUtil::rsaEncrypt($arr, $publicKey);

        // //登录过期设置（15天）
        Redis::SETEX('user_id_'.$userId.'_'.$device, 86400*15, $userId);

        AdminModel::where('id', $userId)->update(['device' => $device]);

        return [
            'code' => 0,
            'msg' => 'success',
            'data' => [
                'user_id' => $userId,
                'token' => $token,
                'company_name' => empty($companyName)?'':$companyName
            ]
        ];
    }

    //注册
    static protected function register($mobile, $device, $miniCode, $bindId, $deviceId)
    {
        $arr['username'] = $mobile;
        $arr['mobile'] = $mobile;
        $arr['created_at'] = time();
        $arr['device'] = $device;
        $arr['bind_id'] = $bindId;

        if(!empty($deviceId)) {
            $arr['device_id'] = $deviceId;
        }

        if(!empty($miniCode)) {
            $result = json_decode(SELF::getOpenId($miniCode), true);
            $arr['openid'] = $result['openid'];
        }

        $insertId = AdminModel::insertGetId($arr);

        $vipInfo = VipSettingModel::where('id', 1)->first();

        AdminAddendumModel::insert([
            'main_id' => $insertId,
            'album_amount' => $vipInfo['album_amount'],
            'album_page_amount' => $vipInfo['album_page_amount'],
            'empty_bill_amount' => $vipInfo['empty_bill_amount'],
            'special_seal' => $vipInfo['special_seal'],
            'one_key_album_times' => $vipInfo['one_key_album_times'],
            'express_check_times' => $vipInfo['express_check_times'],
            'account_storage' => $vipInfo['account_storage'],
            'clear_watermark_or_not' => $vipInfo['clear_watermark_or_not'],
        ]);

        $checkInfo = AdminModel::where('id', $bindId)->first();
        if(!empty($checkInfo)) {
            AdminModel::where('id', $bindId)->increment('invite_num');
        }

        return $insertId;
    }

    static public function moduleCommon($firstModule, $secondModule)
    {
        $firstModuleInfo = ModuleModel::select(
            'id',
            'module_name',
            'upper_module_id',
            'module_img',
            'type',
            'sort',
            'icon',
            'url1',
            'url2'
        )
            ->whereIn('id', $firstModule)
            ->where('delete_flag', 0)
            ->orderBy('sort', 'asc')
            ->orderBy('id', 'DESC')
            ->get()->toArray();

        $secondModuleInfo = ModuleModel::select(
            'id',
            'module_name',
            'upper_module_id',
            'module_img',
            'type',
            'sort',
            'icon',
            'url1',
            'url2'
        )
            ->where('delete_flag', 0)
//            ->whereNotIn('id', [100, 97, 96, 94, 95])
            ->whereIn('id', $secondModule)
            ->orderBy('sort', 'asc')
            ->orderBy('id', 'DESC')
            ->get()->toArray();

        foreach($firstModuleInfo as $key => $value) {
            foreach($secondModuleInfo as $k => $v) {
                if($value['id'] == $v['upper_module_id']) {
                    $firstModuleInfo[$key]['second_module'][] = $v;
                }
            }
        }

        return $firstModuleInfo;
    }

    static public function getOpenId($code)
    {
        $curl = curl_init();

        $url = "https://api.weixin.qq.com/sns/jscode2session?appid=".
            config('app.miniapp_id')."&secret=".
            config('app.miniapp_secret')."&js_code=".$code."&grant_type=authorization_code";

        curl_setopt($curl, CURLOPT_URL, $url);
        curl_setopt($curl, CURLOPT_HEADER, false);
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
        $data = curl_exec($curl);
        curl_close($curl);
        return $data;
    }

    static public function loginLimit($userId, $token, $device)
    {
        if(in_array($device, [1,2,4,5])) {
            Redis::SETEX($userId.'_app', 86400*15, $token);
        }
        else {
            Redis::SETEX($userId.'_pc', 86400*15, $token);
        }

        return true;
    }
}
